/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.support.transform.handler;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.dos.FieldDo;
import cn.easyplatform.dos.Record;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.lang.Lang;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.support.transform.Parameter;
import cn.easyplatform.support.transform.TagNode;
import cn.easyplatform.support.transform.TransformerHandler;
import cn.easyplatform.type.FieldType;
import cn.easyplatform.util.RuntimeUtils;
import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class StructuringHandler implements
		TransformerHandler<Map<String, List<TagNode>>> {

	private final static Logger log = LoggerFactory.getLogger(StructuringHandler.class);

	private CommandContext cc;

	private RecordContext rc;

	private String type;

	private Map<String, String> config;

	/**
	 * @param cc
	 * @param rc
	 */
	public StructuringHandler(CommandContext cc, RecordContext rc, String type) {
		this.cc = cc;
		this.rc = rc;
		this.type = type;
	}

	@Override
	public void transform(Map<String, List<TagNode>> data, Parameter parameter) {
		TagNode root = data.get("").get(0);
		String name = root.getName() + "-" + type;
		config = cc.getProjectService().getConfig().getOptions(name);
		if (config == null)
			throw new EasyPlatformWithLabelKeyException(
					"transformer.config.not.found", name);
		if (type.equals("SWI")) {
			// 创建swift变量
			rc.setVariable(new FieldDo("SWIBLOCK1", FieldType.VARCHAR, data
					.get("1").get(0).getValue()));
			rc.setVariable(new FieldDo("SWIBLOCK2", FieldType.VARCHAR, data
					.get("2").get(0).getValue()));
			rc.setVariable(new FieldDo("SWIBLOCK3", FieldType.VARCHAR, data
					.get("3") == null ? "" : data.get("3").get(0).getValue()));
			rc.setVariable(new FieldDo("SWIBLOCK5", FieldType.VARCHAR, data
					.get("5") == null ? "" : data.get("5").get(0).getValue()));
		}
		BidiMap bmap = new DualHashBidiMap(config);
		eval(data, bmap, root);
	}

	private void eval(Map<String, List<TagNode>> data, BidiMap bmap,
			TagNode parent) {
		String logic = getLogic(config, parent.getPath());
		if (!Strings.isBlank(logic))
			eval(data, bmap, logic, parent);
		else {
			List<TagNode> tns = parent.getChildren();
			for (TagNode tn : tns) {
				if (!tn.isLeaf() && data.containsKey(tn.getPath())) {
					eval(data, bmap, tn);
				}
			}
		}
	}

	private void eval(Map<String, List<TagNode>> data, BidiMap bmap,
			String logic, TagNode node) {
		RecordContext record = rc.clone();
		record.setParameter("759", "IMPORT");
		record.setData(new Record());
		boolean isRoot = false;
		List<String> tags = Lang.array2list(((String) bmap.getKey(logic))
				.split(","));
		if (tags.size() > 1 && node.getParent() != null
				&& node.getParent().getRecord() != null) {
			for (FieldDo field : node.getParent().getRecord())
				record.setVariable(field);
		}
		int level = StringUtils.countMatches(node.getPath(), "/");
		for (String tag : tags) {
			if (StringUtils.countMatches(tag, "/") == level) {
				isRoot = false;
				break;
			}
		}
		if (!isRoot) {
			if (tags.size() == 1 || tags.get(0).equals(node.getPath()))
				isRoot = true;
		}
		tags.remove(node.getPath());
		List<TagNode> tns = node.getChildren();
		List<TagNode> groupNods = new ArrayList<TagNode>();
		for (TagNode t0 : tns) {
			if (t0.isLeaf()) {
				FieldDo field = new FieldDo(isRoot ? t0.getName()
						: node.getName() + t0.getName(), FieldType.VARCHAR,
						t0.getValue());
				record.getData().set(field);
				node.addField(field);
			} else if (tags.contains(t0.getPath())) {
				for (TagNode t1 : t0.getChildren()) {// 二级
					if (t1.isLeaf()) {
						FieldDo field = new FieldDo(
								t0.getName() + t1.getName(), FieldType.VARCHAR,
								t1.getValue());
						record.getData().set(field);
						t0.addField(field);
					} else if (tags.contains(t1.getPath())) {// 三级
						for (TagNode t2 : t1.getChildren()) {
							if (t2.isLeaf()) {
								FieldDo field = new FieldDo(t1.getName()
										+ t2.getName(), FieldType.VARCHAR,
										t2.getValue());
								record.getData().set(field);
								t1.addField(field);
							} else
								groupNods.add(t2);
						}
						tags.remove(t1.getPath());
					} else
						groupNods.add(t1);
				}
				tags.remove(t0.getPath());
			} else
				groupNods.add(t0);
		}
		// 多个配置在同一个逻辑，注意，要在同一层级
		if (!tags.isEmpty() && node.getParent() != null) {
			tns = node.getParent().getChildren();
			for (TagNode tn : tns) {
				if (!tn.isLeaf() && tags.contains(tn.getPath())) {
					for (TagNode t : tn.getChildren()) {// 二级
						if (t.isLeaf())
							record.getData().set(
									new FieldDo(tn.getName() + t.getName(),
											FieldType.VARCHAR, t.getValue()));
						else if (tags.contains(t.getPath())) {// 三级
							for (TagNode tt : t.getChildren()) {
								if (tt.isLeaf())
									record.getData().set(
											new FieldDo(t.getName()
													+ tt.getName(),
													FieldType.VARCHAR, tt
															.getValue()));
								else
									groupNods.add(tt);
							}
							tags.remove(t.getPath());
							data.remove(t.getPath());
						} else
							groupNods.add(t);
					}
					tags.remove(tn.getPath());
					data.remove(tn.getPath());
				}
			}
		}// if
		tags = null;
		tns = null;
		record.setParameter("857", node.getCountIndex());
		if (log.isDebugEnabled())
			log.debug("{}->{}", node.getPath(), record.getData().getData());
		String code = RuntimeUtils.eval(cc, logic, record);
		if (!code.equals("0000")) {// 如果855为true，表示忽略错误
			if (!record.getParameterAsBoolean("855"))
				throw new EasyPlatformWithLabelKeyException(
						"transformer.return.code", logic, cc.getMessage(code,
								record));
		} else {
			if (!groupNods.isEmpty()) {
				for (TagNode tn : groupNods)
					eval(data, bmap, tn);
			}
		}
		groupNods = null;
	}

	private String getLogic(Map<String, String> config, String path) {
		for (Map.Entry<String, String> e : config.entrySet()) {
			String[] tags = e.getKey().split(",");
			for (String tag : tags) {
				if (path.equals(tag))
					return e.getValue().trim();
			}// for
		}// for
		return null;
	}
}
